package com.tegistuff.palmrun;

import com.palm.webos.sdk.SDK;
import com.palm.webos.shell.CommandSet;
import com.palm.webos.shell.CommandShell;
import com.palm.webos.tools.packager.PackageConfig;
import com.palm.webos.tools.packager.PackageContents;
import com.palm.webos.tools.packager.PackageScanner;

import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

/**
 * Main.java
 *
 * Copyright (C) 2011-2012 Timo Tegtmeier.
 * Copyright (C) 2011 Janni Kovacs.
 * All rights reserved.
 */
public class Main {

    private static String BUILD_ONLY = "BUILD_ONLY";
    private static String BUILD_AND_RUN = "BUILD_AND_RUN";
    private static String BUILD_RUN_LOG = "BUILD_RUN_LOG";
    private static String LOG_ONLY = "LOG_ONLY";
    
	public static void main(String[] args) {
		int sdkVersion = getSDKVersion();
		String targetDevice = args[0];
		String appFolder = args[1];

		String[] arguments = new String[args.length - 2];
		System.arraycopy(args, 2, arguments, 0, arguments.length);
		Properties settings = new Properties();
		for (String argument : arguments) {
			String[] kv = argument.split("=");
			settings.put(kv[0], kv[1]);
		}

		boolean useV1 = Boolean.parseBoolean(settings.getProperty("use-v1", "false"));
        String outputFolder = settings.getProperty("output", "");
        String packageFolder = settings.getProperty("pkg", "");
        String serviceFolder = settings.getProperty("srv", "");
        String accountFolder = settings.getProperty("acc", "");
        
		File appDir = new File(appFolder);
        String outputPath = appDir.getParentFile().getAbsolutePath();
        if(!outputFolder.isEmpty())
            outputPath = getFolderPath(outputFolder, outputFolder);

		Logger logger = Logger.getLogger("com.palm.webos.tools");
		logger.setUseParentHandlers(false);

		if (sdkVersion < 2) {
			System.err.println(
                "Running Apps is not supported anymore with the webOS SDK 1.4.5\n" +
                "Please update to the most recent webOS SDK 2.1 (http://developer.palm.com)\n" +
                "You will still be able to run webOS 1.4.5 in the emulator and create 1.x compatible packages.");
            System.exit(20);
        }

        CommandSet commands = new CommandSet();
        commands.addCommand("package", "palm-package", com.palm.webos.tools.shell.Package.class);
        commands.addCommand("install", "palm-install", com.palm.webos.tools.shell.Install.class);
        commands.addCommand("launch", "palm-launch", com.palm.webos.tools.shell.Launch.class);
        commands.addCommand("log", "palm-log", com.palm.webos.tools.shell.Log.class);

        CommandShell shell = new CommandShell(SDK.getInfo(), commands, logger);
        int exitCode = 0;

        if(runBuild(settings)) {
            List<String> ppArgs = new LinkedList<String>();
            if(useV1)
                ppArgs.add("--use-v1-format");
            ppArgs.add("-o");
            ppArgs.add(outputPath);
            if(!packageFolder.isEmpty())
                ppArgs.add(getFolderPath(packageFolder));
            ppArgs.add(appDir.getAbsolutePath());
            if(!serviceFolder.isEmpty())
                ppArgs.add(getFolderPath(serviceFolder));
            if(!accountFolder.isEmpty())
                ppArgs.add(getFolderPath(accountFolder));

            File outputPathFile = new File(outputPath);
            if(!outputPathFile.exists()) {
                System.out.print("Output path does not exists; trying to create it.\n\r");
                if(!outputPathFile.mkdirs()) {
                    System.err.printf("Unable to create output path '%s'! Stopping now.\n\r", outputPath);
                    System.exit(1);
                }
            }
            exitCode = shell.parseCommand("palm-package", ppArgs.toArray(new String[0]));
        }

        PackageConfig config = new PackageConfig();
        config.addSource(appDir);
        PackageScanner scanner = new PackageScanner(config);
        PackageContents contents = null;
        try {
            contents = scanner.readContents();
        } catch (Exception e) {
            exitCode = 2;
        }
        checkExit(exitCode, "Error packaging or scanning the app, exiting.");

        String appId = contents.getPackageId();
        String ipkFileName = appId + "_" + contents.getPackageVersion() + "_all.ipk";
        File ipkFile = new File(outputPath, ipkFileName);

        if(runApp(settings)) {
            exitCode = shell.parseCommand("palm-install", new String[]{"-d", targetDevice, ipkFile.getAbsolutePath()});
            checkExit(exitCode, "Error installing the app, exiting.");
    
            exitCode = shell.parseCommand("palm-launch", new String[]{"-d", targetDevice, appId});
            checkExit(exitCode, "Error launching the app, exiting.");
        }

        if(runLog(settings)) {
            shell.parseCommand("palm-log", new String[]{"-d", targetDevice, "-f", appId});
        }

        System.exit(0);
	}

    /**
     * Returns 1 or 2 for 1.x and 2.x versions respectively
     *
     * @return 1 or 2
     */
    private static int getSDKVersion() {
        try {
            Class.forName("com.palm.webos.sdk.SDK");
            return 2;
        } catch (ClassNotFoundException e) {
            return 1;
        }
    }

    private static String getFolderPath(String file) {
        return getFolderPath(file, "");
    }
    
    private static String getFolderPath(String file, String failStr) {
        File folder = new File(convertPath(file));
        if(folder.isDirectory())
            return folder.getAbsolutePath();
        return convertPath(failStr);
    }

	private static void checkExit(int exitCode, String message) {
		if (exitCode != 0) {
			System.err.println(message);
			System.exit(exitCode);
		}
	}
    
    private static String convertPath(String path) {
        return path.replace('\\', File.separatorChar).replace('/', File.separatorChar);
    }
    
    private static String getBuildMode(Properties settings) {
        return settings.getProperty("mode", BUILD_RUN_LOG);
    }
    
    private static boolean runBuild(Properties settings) {
        String mode = getBuildMode(settings);
        return mode.equals(BUILD_ONLY) || mode.equals(BUILD_AND_RUN) || mode.equals(BUILD_RUN_LOG);
    }

    private static boolean runApp(Properties settings) {
        String mode = getBuildMode(settings);
        return mode.equals(BUILD_AND_RUN) || mode.equals(BUILD_RUN_LOG);
    }

    private static boolean runLog(Properties settings) {
        String mode = getBuildMode(settings);
        return mode.equals(BUILD_RUN_LOG) || mode.equals(LOG_ONLY);
    }
}
